const http = require("http");
const https = require("https");
const querystring = require("querystring");

function httpGet(url) {
    return new Promise(function (resolve, reject) {
        http.get(url, res=>{
            let _data = null;
            res.on('data', function (chunk) {
                if (_data) {
                    _data = Buffer.concat([_data, chunk]);
                } else {
                    _data = Buffer.from(chunk);
                }
            });
            res.on("end", function () {
                res.body = _data;
                resolve(res);
            });
        }).on("error", err=>{
            console.error(err);
            reject(err);
        });
    })
}

function httpsGet(url, headers=null) {
    return new Promise(function (resolve, reject) {
        let options = {headers:headers};
        https.get(url, options, res=>{
            let _data = null;
            res.on('data', function (chunk) {
                if (_data) {
                    _data = Buffer.concat([_data, chunk]);
                } else {
                    _data = Buffer.from(chunk);
                }
            });
            res.on("end", function () {
                res.body = _data;
                resolve(res);
            });
        }).on("error", err=>{
            console.error(err);
            reject(err);
        });
    })
}

function post(client, url, data, type, headers, pfx, callback) {
    let content_type = null;
    switch (type) {
        case "json":
            content_type = "application/json";
            break;
        case "xml":
            content_type = "application/xml";
            break;
        case "from-urlencoded":
            content_type = "application/x-www-form-urlencoded";
            break;
        case "html":
            content_type = "text/html";
            break;
        case "binary":
            content_type = "application/octet-stream";
            break;
        default:
            content_type = "text/plain";
            break;
    }
    let options = {
        // hostname: 'oapi.dingtalk.com',
        // port: 443,
        method: 'POST',
        json: type=="json",
        pfx: pfx?pfx.file:null,
        passphrase: pfx?pfx.pwd:null
    };
    const buf = Buffer.from(data);
    if (headers) {
        if (!headers['Content-Type']) {
            headers['Content-Type'] = content_type;
        }
        if (!headers['Content-Length']) {
            headers['Content-Length'] = buf.length;
        }
        options.headers = headers;
    } else {
        options.headers = {
            'Content-Type': content_type,
            'Content-Length': buf.length
        };
    }
    let req = client.request(url, options, res => {
        // console.log("statusCode: ", res.statusCode);
        let _data = null;
        res.on('data', function (chunk) {
            if (_data) {
                _data = Buffer.concat([_data, chunk]);
            } else {
                _data = Buffer.from(chunk);
            }
        });
        res.on('end', function () {
            if (callback) {
                res.body = _data;
                callback(null, res);
            }
        });
    });
    req.on('error', (e) => {
        callback(e.message, null);
    });
    req.write(buf);
    req.end();
}

function httpPost(url, data, type="json", headers=null) {
    return new Promise(function (resolve, reject) {
        post(http, url, data, type, headers, null, function(error, res) {
            if (error) {
                console.error(error);
                reject(error);
            } else {
                resolve(res);
            }
        });
    })
}

function httpsPost(url, data, type="json", headers=null, fpx=null) {
    return new Promise(function (resolve, reject) {
        post(https, url, data, type, headers, fpx, function(error, res) {
            if (error) {
                console.error(error);
                reject(error);
            } else {
                resolve(res);
            }
        });
    })
}

function joinUrlParam(obj, flag='&', skip='=') {
    // 获取对象的所有键
    const keys = Object.keys(obj);
    // 按键名升序排序
    keys.sort();
    
    const arr = [];
    for (const key of keys) {
        if (key.indexOf(skip)==-1) {
            arr.push(`${key}=${obj[key]}`);
        }
    }
    return arr.join(flag);
}

function urlParamToObject(str) {
    const params = querystring.parse(str);
    return params;
}

module.exports.httpGet = httpGet;
module.exports.httpsGet = httpsGet;
module.exports.httpPost = httpPost;
module.exports.httpsPost = httpsPost;
module.exports.joinUrlParam = joinUrlParam;
module.exports.urlParamToObject = urlParamToObject;